﻿using System;
using System.Diagnostics;
using NUnit.Framework;
using octalforty.Componento.ComponentModel.Tracing;
using Rhino.Mocks;

namespace octalforty.Componento.Tests.Componento.ComponentModel.Tracing
{
    [TestFixture()]
    public class TraceManagerServiceTestFixture
    {
        [Test()]
        public void WriteWhenNoTraceWritersRegistered()
        {
            var traceManager = new TraceManagerService();

            try
            {
                traceManager.Write(TraceLevel.Info, "Foo", "Bar");
            } // try
            catch(Exception)
            {
                Assert.Fail();
            } // catch
        }

        [Test()]
        public void TraceManagerServiceAllowsUnbalancedLogicalOperations()
        {
            var traceManager = new TraceManagerService();

            traceManager.BeginLogicalOperation();
            traceManager.EndLogicalOperation();
            traceManager.EndLogicalOperation();
        }

        [Test()]
        public void Trace()
        {
            var mockRepository = new MockRepository();

            var traceWriter1 = mockRepository.StrictMock<ITraceWriter>();
            var traceWriter2 = mockRepository.StrictMock<ITraceWriter>();
            var dateTime = DateTime.Now;

            using(mockRepository.Record())
            {
                Expect.Call(() => traceWriter1.Write(dateTime, TraceLevel.Error, 0, "Foo", "Level 0"));
                Expect.Call(() => traceWriter2.Write(dateTime, TraceLevel.Error, 0, "Foo", "Level 0"));
                Expect.Call(() => traceWriter1.Write(dateTime, TraceLevel.Info, 1, "Bar", "Level 1"));
                Expect.Call(() => traceWriter2.Write(dateTime, TraceLevel.Info, 1, "Bar", "Level 1"));
                Expect.Call(() => traceWriter1.Write(dateTime, TraceLevel.Warning, 2, "Baz", "Level 2"));
                Expect.Call(() => traceWriter2.Write(dateTime, TraceLevel.Warning, 2, "Baz", "Level 2"));
                Expect.Call(() => traceWriter1.Write(dateTime, TraceLevel.Verbose, 0, "Qux", "Level 0"));
                Expect.Call(() => traceWriter2.Write(dateTime, TraceLevel.Verbose, 0, "Qux", "Level 0"));
            } // using

            var traceManager = new TraceManagerService()
                {
                    TraceWriters = new[]
                        {
                            new Lazy<ITraceWriter>(() => traceWriter1),
                            new Lazy<ITraceWriter>(() => traceWriter2), 
                        },
                    DateTimeProvider = () => dateTime
                };

            traceManager.Write(TraceLevel.Error, "Foo", "Level 0");

            traceManager.BeginLogicalOperation();
            traceManager.Write(TraceLevel.Info, "Bar", "Level 1");

            traceManager.BeginLogicalOperation();
            traceManager.Write(TraceLevel.Warning, "Baz", "Level 2");

            traceManager.EndLogicalOperation();
            traceManager.EndLogicalOperation();
            traceManager.Write(TraceLevel.Verbose, "Qux", "Level 0");

            mockRepository.VerifyAll();
        }
    }
}
